import http from '@ohos.net.http';
import utils from '../../core/utils';
import logger from '../../core/logger';
import current from '../../core/current';
import apiKeyInfo from '../../model/common/apiKeyInfo';
import { API_USER_AGENT, HOST } from '../../core/dict';

export default class apiProvider {
  public static readonly Build4: string = "421000";
  public static readonly Build5: string = "5520400";
  public static readonly Build6: string = "6235200";
  public static readonly Build7: string = "7270300";
  public static readonly LoginKey: apiKeyInfo = new apiKeyInfo("783bbb7264451d82", "2653583c8873dea268ab9386918b1d65");
  public static readonly AndroidKey: apiKeyInfo = new apiKeyInfo("1d8b6e7d45233436", "560c52ccd288fed045859ed18bffd973");
  public static readonly WebVideoKey: apiKeyInfo = new apiKeyInfo("84956560bc028eb7", "94aba54af9065f71de72f5508f1cd42e");
  public static readonly AndroidTVKey: apiKeyInfo = new apiKeyInfo("4409e2ce8ffd12b8", "59b43e04ad6965f34319062b478f83dd");
  public static readonly AndroidVideoKey: apiKeyInfo = new apiKeyInfo("iVGUTjsxvpLeuDCf", "aHRmhWMLkdeMuILqORnYZocwMBpMEOdt");
  private static mixinKeyEncTab: number[] = [
    46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
    33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
    61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
    36, 20, 34, 44, 52];

  public static get timeSpanSeconds(): number {
    return new Date().valueOf();
  }

  public static get accessKey() {
    return current.instance.accesskey;
  }

  public static getWbiSign(url: string): Promise<string> {
    return new Promise((resolve) => {
      let params = this.sort(url, 1);
      this.getResult().then((res) => {
        var imgUrl: string = res.data.wbi_img.img_url.toString();
        var subUrl: string = res.data.wbi_img.sub_url.toString();
        var imgKey = imgUrl.slice(imgUrl.lastIndexOf('/') + 1, imgUrl.lastIndexOf('.'));
        var subKey = subUrl.slice(subUrl.lastIndexOf('/') + 1, subUrl.lastIndexOf('.'));
        let temp: string = '', orig = imgKey + subKey;
        this.mixinKeyEncTab.forEach((n) => temp += orig[n]);
        let mixin_key = temp.slice(0, 32),
          curr_time: number = Math.round(Date.now() / 1000),
          chr_filter: RegExp = /[!'\(\)*]/g;
        let query = [];
        if (typeof params !== 'string') {
          const params2 = Object.assign(params, {
            wts: curr_time
          });
          Object.keys(params2).sort().forEach((key: string) => query.push(`${encodeURIComponent(key)}=${encodeURIComponent(('' + params2[key]).replace(chr_filter, ''))}`));
          const queryStr: string = query.join('&');
          const wbiSign = utils.md5(queryStr + mixin_key);
          resolve(`${queryStr}&w_rid=${wbiSign}`);
        } else
          resolve('');
      });
    });
  }

  private static getResult(): Promise<any> {
    return new Promise(async (resolve) => {
      let httpRequest = http.createHttp();
      httpRequest.request('https://api.bilibili.com/x/web-interface/nav', {
        method: http.RequestMethod.GET,
        header: {
          "referer": HOST,
          "app-key": "android64",
          "user-agent": API_USER_AGENT,
          "x-bili-aurora-zone": "sh001",
          "x-bili-aurora-eid": "UlMFQVcABlAH"
        },
        connectTimeout: 5000,
        readTimeout: 5000
      }, (err, data) => {
        try {
          if (!err && data.responseCode == http.ResponseCode.OK) {
            if (typeof data.result == 'string') {
              var json = JSON.parse(data.result.toString());
              resolve(json);
            } else {
              var json = String.fromCharCode.apply(null, new Uint16Array(data.result as ArrayBuffer));
              resolve(json);
            }
          } else {
            logger.info('gethttp error:' + JSON.stringify(err));
            resolve(err.message);
          }
        } catch (e) {
          logger.error(e);
          resolve(e);
        }
        httpRequest.destroy();
      });
    });
  }

  public static getSign(url: string, keyInfo?: apiKeyInfo): string {
    let sign = this.sort(url, 0);
    sign += keyInfo.secret;
    return utils.md5(sign);
  }

  private static sort(url: string, type: number): string | object {
    if (type == 0) {
      let sign = '';
      if (url.indexOf('?') > -1) {
        let index = url.indexOf("?", 4) + 1;
        let str = url.substring(index);
        let array = str.split('&').sort();
        for (let i = 0;i < array.length; i++) {
          if (array[i].length > 0) {
            if (sign.length != 0)
              sign += '&';
            sign += array[i];
          }
        }
      } else {
        if (url.startsWith('&'))
          url = url.substring(1);
        let array = url.split('&').sort();
        for (let i = 0;i < array.length; i++) {
          if (array[i].length > 0) {
            if (sign.length != 0)
              sign += '&';
            sign += array[i];
          }
        }
      }
      return sign;
    } else {
      if (url.startsWith('&'))
        url = url.substring(1);
      return utils.parseQueryString(url);
    }
  }
}